package flib;

import flib.SplitArea.Pair;
import importExport.SVGText;

import java.util.Collections;
import java.util.Vector;

import simpleGeom.Bounds2D;

import simpleGeom.HasPos2D;
import simpleGeom.HasPos3D;
import simpleGeom.Triangulator;
import simpleGeom.Vec2D;

public class Room extends FlibFace{
	public int id;

Vector<Room>children=new Vector<Room>();


Vector<EdgeSegment>segments;

public boolean ispublic;
public boolean checked;
SVGText label;
Split split;
public int seg1;
public int seg2;
public float relPos1;
public float relPos2;
public boolean it;
public boolean cold;

Vector<FlibHEdge>innerRooms=new Vector<FlibHEdge>();

public void setPts(Vector<FlibHEdge>hEdges){
	FlibHEdge hEdge=null;
	for (int i=0;i<hEdges.size();i++){
		 hEdge=hEdges.get(i);
		hEdge.attach();
	}
	this.setHEdge(hEdge.getSym());
}
public boolean isSteps() {
	return steps;
}
public void setSteps(boolean steps) {
	this.steps = steps;
}


public void collectAllLeaves(Vector<Room>leaves){
	if (children.size()==0){
		leaves.add(this);
		return;
	}
	for (int i=0;i<children.size();i++){
		Room sA=children.get(i);
		sA.collectAllLeaves(leaves);
	}
}
public void initCornerPts(){
	Vector<FlibHENode> nodes=this.getFaceNodes();
	for (int i=0;i<nodes.size();i++){
		int i1=i;
		int i2=(i+1)%nodes.size();
		int i3=(i+2)%nodes.size();
		FlibHENode p1=nodes.get(i1);
		FlibHENode p2=nodes.get(i2);
		FlibHENode p3=nodes.get(i3);
		float angle=Vec2D.getAngleBetween(p1, p2, p3);
		if (angle<Math.PI*0.8f){
			NodeData n=(NodeData) p2.getData();
			n.setCorner(true);
		}
	}
}
public void setCornerPts(){
	Bounds2D b2d=(Bounds2D) this.getBounds2D();
	float closestD=Float.MAX_VALUE;
	Vec2D corner=new Vec2D(b2d.x1,b2d.y1);
	FlibHEdge closestHEdge=null;
	FlibHEdge hE=this.getHEdge();
	do{
		NodeData nD=(NodeData) hE.getOrg().getData();
		if (nD.isCorner()){
			float cD=hE.getOrg().dist(corner);
			if (cD<closestD){
				closestHEdge=hE;
				closestD=cD;
			}
		}
		hE=hE.getNext();
	}while(hE!=this.getHEdge());
	//closestHEdge=hE;
	hE=closestHEdge;
	//hE=this.getHEdge();
	segments=new Vector<EdgeSegment>();
	do{
		NodeData nD=(NodeData) hE.getOrg().getData();
		if (nD.isCorner()){
			EdgeSegment seg=new EdgeSegment();
			seg.hEdge=hE;
			segments.add(seg);
			// sammeln.
		}
		hE=hE.getNext();
	}while(hE!=closestHEdge);
	
}

public boolean contains(Split split){
	int id=0;
	// how to detect a real split...
	Vector<HasPos2D>splitPts=split.getPts();
	
	int i1=-1;
	int i2=-1;
	
	// contains...
	// genau zwei punkte im ring. 
	// beide punkte mit abstand im Ring
	
	Vector<FlibHENode>nodes=this.getFaceNodes();
	for (int i=0;i<splitPts.size();i++){
		FlibHENode p=(FlibHENode) splitPts.get(i);
		int cI=nodes.indexOf(p);
		if (cI>=0){
			id++;
			if (i1<0){
				i1=cI;
			}
			else if (i2<0){
				i2=cI;
			}
			else return false;//mehr als 2 punkte
		}
		
	}
	if (id!=2)return false;
	if (((i1+1)%nodes.size())==i2)return false;
	if (((i2+1)%nodes.size())==i1)return false;
	

	return true;
}
public Vector<Room> split(int seg1,int seg2,float relPos1,float relPos2) {
	setCornerPts();
	if (seg1>=segments.size()||seg2>=segments.size()){
		System.out.println("too much");
	}
	
	EdgeSegment segE1=segments.get(seg1%segments.size());//%segments.size()
	FlibHENode n1=segE1.getNode(relPos1);
	EdgeSegment segE2=segments.get(seg2%segments.size());//%segments.size()
	FlibHENode n2=segE2.getNode(relPos2);
	NodeData nd=new NodeData();
	nd.corner=true;
	n1.data=nd;
	NodeData nd2=new NodeData();
	nd2.corner=true;
	n2.data=nd2;
	
	FlibHEdge hEdge1=new FlibHEdge(n1,n2);
	hEdge1.attach();
	
	Room room1 = new Room();
	room1.setHEdge(hEdge1);
	hEdge1.setFaceToAll(room1);
	
	Room room2 = new Room();
	room2.setHEdge(hEdge1.getSym());
	hEdge1.getSym().setFaceToAll(room1);

	Vector<Room> rooms = new Vector<Room>();
	rooms.add(room1);
	rooms.add(room2);
	room1.setCornerPts();
	room2.setCornerPts();
	children.add(room1);
	children.add(room2);
	
	System.out.println("s1: "+room1.segments.size());
	System.out.println("s2: "+room2.segments.size());
	return rooms;
}
	public Vector<Room> split(Split split) {
		setCornerPts();
		Vector<FlibHENode> nodes = this.getFaceNodes();
		Vector<HasPos2D> splitpts = split.getPts();
		int i1 = -1;
		int i2 = -1;
		for (int i = 0; i < splitpts.size(); i++) {
			FlibHENode p = (FlibHENode) splitpts.get(i);
			for (int j = 0; j < segments.size(); j++) {
				EdgeSegment seg = segments.get(j);
				Vector<FlibHENode> segPts = seg.getNodes();
				int cI = segPts.indexOf(p);
				if (cI >= 0) {
					if (i1 < 0) {
						i1 = i;
						seg1 = j;
						relPos1 = seg.getLength(p)/seg.getLength();
					} else {
						i2 = i;
						seg2 = j;
						relPos2 = seg.getLength(p)/seg.getLength();
						i=splitpts.size();
						break;
					}
				}
			}
		}
		
		
		for (int i = i1; i < i2; i++) {
			FlibHEdge hEdge = split.hEdges.get(i);
			hEdge.attach();
		}
		FlibHEdge hEdge1 = split.hEdges.get(i1);
		FlibHENode sN1=(FlibHENode)splitpts.get(i1);
		FlibHENode sN2=(FlibHENode)splitpts.get(i2);
		NodeData nD=new NodeData();
		nD.corner=true;
		NodeData nD2=new NodeData();
		nD2.corner=true;
		sN1.data=nD;
		sN2.data=nD2;
		Room room1 = new Room();
		room1.setHEdge(hEdge1);
		hEdge1.setFaceToAll(room1);
		Room room2 = new Room();
		room2.setHEdge(hEdge1.getSym());
		hEdge1.getSym().setFaceToAll(room1);

		Vector<Room> rooms = new Vector<Room>();
		rooms.add(room1);
		rooms.add(room2);
		room1.setCornerPts();
		room2.setCornerPts();
		children.add(room1);
		children.add(room2);
		this.split=split;
		System.out.println("seg1: "+seg1+" seg2: "+seg2+" rel1 "+relPos1+" rel2 "+relPos2);
		return rooms;
	}
	public Vector<HasPos2D[]> calcTriangles(){
		Vector<FlibHENode>nodes=simpliFiedOutline();
		Vector<FlibHENode>indnodes=new	Vector<FlibHENode>();
		for (int j=0;j<nodes.size();j++){
			FlibHENode n=nodes.get(j);
			if (indnodes.contains(n)){
				FlibHENode newN=new FlibHENode(n.x,n.y);
				indnodes.add(newN);
			}
			else{
				indnodes.add(n);
			}
		}
		if (indnodes.size()>3){
		Triangulator tri=new Triangulator(indnodes);
		tri.triangulate();
		return tri.triangles;
		}
		return null;
	}
	public boolean isCold() {
		if (type==null)return cold;
		return !type.isWarm();
	}
	public void setCold(boolean cold) {
		this.cold = cold;
	}
	public boolean isPublic() {
		if (type==null)return ispublic;
		return type.isPublic();
	}
	public void setPublic(boolean ispublic) {
		this.ispublic = ispublic;
	}
	
}
